// Copyright 2023 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <Common/PODArray.h>
#include <IO/Compression/ICompressionCodec.h>

namespace DB
{
class ReadBuffer;

/** Basic functionality for implementation of
  *  CompressedReadBuffer and CompressedReadBufferFromFile.
  * has_legacy_checksum:
  *   For the clickhouse implementation, there is a built-in checksum inside
  *   CompressedReadBufferBase. But for TiFlash, we use `FramedChecksumReadBuffer`
  *   to handle the checksum. TiFlash set `has_legacy_check = false` for the new IO
  *   implementation.
  */
template <bool has_legacy_checksum = true>
class CompressedReadBufferBase
{
protected:
    ReadBuffer * compressed_in;
    CompressionCodecPtr codec;
    /// If 'compressed_in' buffer has whole compressed block - then use it. Otherwise copy parts of data to 'own_compressed_buffer'.
    PODArray<char> own_compressed_buffer;
    /// Points to memory, holding compressed block.
    char * compressed_buffer = nullptr;

    /// Don't checksum on decompressing.
    bool disable_checksum[has_legacy_checksum]{};


    /// Read compressed data into compressed_buffer. Get size of decompressed data from block header. Checksum if need.
    /// Returns number of compressed bytes read.
    size_t readCompressedData(size_t & size_decompressed, size_t & size_compressed_without_checksum);

    void decompress(char * to, size_t size_decompressed, size_t size_compressed_without_checksum);

public:
    /// 'compressed_in' could be initialized lazily, but before first call of 'readCompressedData'.
    explicit CompressedReadBufferBase(ReadBuffer * in = nullptr);
    ~CompressedReadBufferBase();

    /** Disable checksums.
      * For example, may be used when
      *  compressed data is generated by client, that cannot calculate checksums, and fill checksums with zeros instead.
      */
    void disableChecksumming()
    {
        if constexpr (has_legacy_checksum)
        {
            disable_checksum[0] = true;
        }
    }
};


} // namespace DB
